﻿using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MJB.UI.ContentEditor.Commands;
using MJB.UI.ContentEditor.Windows;
using MJB.UI.ContentEditor.Document;
using MJB.UI.ContentEditor.Document.Version1;

namespace MJB.UI.ContentEditor.UserControls
{
    /// <summary>
    /// Interaction logic for SectionListBoxControl.xaml
    /// </summary>
    public partial class SectionListBoxControl : UserControl
    {

        #region Constructor

        /// <summary>
        /// Creates the section list box control.
        /// </summary>
        public SectionListBoxControl()
        {
            InitializeComponent();
            SuggestionCommands.RegisterCommandHandlers(mSectionTextBox);
        }

        #endregion
        #region Public Properties

        /// <summary>
        /// This property is used to access the section text box.
        /// </summary>
        public TextBox SectionTextBox
        {
            get
            {
                return mSectionTextBox;
            }
        }

        #endregion
        #region Public Methods
        #endregion
        #region Event Handlers

        /// <summary>
        /// Called when the move up button is pressed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnMoveUpButtonClicked(object sender, RoutedEventArgs args)
        {
            ISection section = (ISection)this.DataContext;

            MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
            ObservableCollection<ISection> sections = mainWindow.DisplayedReader.Sections;

            for(int i = 1; i < sections.Count; i++)
            {
                if(sections[i] == section)
                {
                    sections[i] = sections[i - 1];
                    sections[i - 1] = section;
                    return;
                }

            }

        }

        /// <summary>
        /// Called when the move down button is pressed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnMoveDownButtonClicked(object sender, RoutedEventArgs args)
        {
            ISection section = (ISection)this.DataContext;

            MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
            ObservableCollection<ISection> sections = mainWindow.DisplayedReader.Sections;

            for(int i = 0; i < sections.Count - 1; i++)
            {
                if(sections[i] == section)
                {
                    sections[i] = sections[i + 1];
                    sections[i + 1] = section;
                    return;
                }
            }

        }

        /// <summary>
        /// Called when the delete button is pressed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnDeleteButtonClicked(object sender, RoutedEventArgs args)
        {
            ISection section = (ISection)this.DataContext;

            MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
            ObservableCollection<ISection> sections = mainWindow.DisplayedReader.Sections;

            if(sections.Count == 1)
            {
                section.SectionText = String.Empty;
                section.SectionTitle = "Untitled";
                section.UsesLastModified = false;
                return;
            }

            // Once we find the section to remove, remove it from the list.
            for(int i = 0; i < sections.Count; i++)
            {
                if(sections[i] == section)
                {
                    sections.RemoveAt(i);
                    return;
                }
            }

        }

        /// <summary>
        /// Called when the validate button is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnValidateXMLButtonClicked(object sender, RoutedEventArgs args)
        {
            ISection section = (ISection)this.DataContext;

            XmlTextReader textReader = null;
            try
            {
                textReader = new XmlTextReader(section.SectionText, XmlNodeType.Element, null);
                while(textReader.Read())
                {
                    // Do nothing:
                }

                "This section was validated successfully!".DisplayMessageDialog();

            }
            catch(XmlException e)
            {
                e.DisplayError("This section has some invalid XML!");
            }
            finally
            {
                if(textReader != null)
                    textReader.Close();
            }

        }

        /// <summary>
        /// Called when the uses last modified check box is checked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnUsesLastModifiedCheckBoxChecked(object sender, RoutedEventArgs args)
        {
            ISection section = (ISection)this.DataContext;
            section.UsesLastModified = true;

            if(section.LastModified == DateTime.MaxValue)
                section.LastModified = DateTime.Now;

        }

        /// <summary>
        /// Called when the control recieves a key down event.  Sometimes we want
        /// to catch a key down event before it makes it anywhere else.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnPreviewKeyDown(object sender, KeyEventArgs e)
        {
            if(e.OriginalSource != mSectionTextBox)
                return;

            // The < character comes from shift + comma:
            if(e.Key == Key.OemComma && e.KeyboardDevice.Modifiers == ModifierKeys.Shift)
            {
                // Determine the location of the suggestion box:
                Rect r = mSectionTextBox.GetRectFromCharacterIndex(mSectionTextBox.CaretIndex);

                mSuggestionPopup.HorizontalOffset = r.BottomRight.X;
                mSuggestionPopup.VerticalOffset = r.Top;

                mSuggestionPopup.IsOpen = true;
                mSectionTextBox.Focus();

            }
            else if(mSuggestionPopup.IsOpen)
            {
                // If the up or down buttons are clicked, 
                // then we move the selected item in the suggestion list box:
                if(e.Key == Key.Up)
                {
                    mSuggestionListBox.SelectedIndex = (mSuggestionListBox.SelectedIndex <= 0)
                         ? mSuggestionListBox.Items.Count - 1
                         : mSuggestionListBox.SelectedIndex - 1;

                    e.Handled = true;
                }
                else if(e.Key == Key.Down)
                {
                    mSuggestionListBox.SelectedIndex = (mSuggestionListBox.SelectedIndex == mSuggestionListBox.Items.Count - 1)
                         ? 0
                         : mSuggestionListBox.SelectedIndex + 1;

                    e.Handled = true;
                }
                else if(e.Key == Key.Enter && mSuggestionListBox.SelectedIndex > -1)
                {
                    RoutedUICommand command = (RoutedUICommand)mSuggestionListBox.Items[mSuggestionListBox.SelectedIndex];
                    command.Execute(this, mSectionTextBox);
                    mSuggestionPopup.IsOpen = false;
                    e.Handled = true;

                }
                else
                {                    
                    mSuggestionPopup.IsOpen = false;
                }

            }

        }


        /// <summary>
        /// Called when the section list box recieves a key up event.  After the command
        /// key is released and the carret is moved on the text box, we need to move the 
        /// suggestion list box.  Otherwise, the &lt; character will be blocked by the list
        /// box.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnPreviewKeyUp(object sender, KeyEventArgs e)
        {
            if(mSuggestionPopup.IsOpen)
            {
                Rect r = mSectionTextBox.GetRectFromCharacterIndex(mSectionTextBox.CaretIndex);
                mSuggestionPopup.HorizontalOffset = r.BottomRight.X;
                mSuggestionPopup.VerticalOffset = r.Top;
            }
        }

        /// <summary>
        /// If the section text box loses focus and the suggestion list box is being display,
        /// close it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSectionTextBoxLostFocus(object sender, RoutedEventArgs e)
        {
            mSuggestionPopup.IsOpen = false;
        }

        #endregion

    }

}
